home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
mg
/
docs
/
config
< prev
next >
Wrap
Text File
|
1995-03-09
|
28KB
|
671 lines
CONFIG USERS MANUAL
0. TABLE OF CONTENTS
0. TABLE OF CONTENTS
1. INTRODUCTION
1.1 Description
1.2 Overview
1.3 Conventions
2. PREPARING A CONFIGURATION
2.1 Syntax
2.2 Options Files
2.3 Configuration Files
3. PREPARING OPTIONS FILES
3.1 Value Options
3.2 Option Options
3.3 Required Options
3.4 Action Options
3.5 Names To Avoid
4. PROGRAMMING FOR CONFIG
4.1 Starting Out
4.2 Required Options
4.3 Option Options
4.4 Value Options
4.5 The "Appropriate" Options File
4.6 Converting a Program for Config
1. INTRODUCTION
This section describes config, gives an overview of this manual, and
introduces the user to the conventions and terminology of config.
1.1 Description
Config is a tool that makes configuring a certain type of large
program much easier for anyone not intimately familiar with the
details of the program. It also makes keeping multiple different
configurations of such programs easier - even though they may run on
different machines, or under different operating systems.
The programs in question all use numerous symbols to control the
conditional compilation of features in the program, or to control
which code is compiled for what system. These programs need to run on
multiple different machines or operating systems, or run in an
environment where having all the features of a program enabled entails
an unacceptable performance cost, or makes running the program
impossible.
The two normal approaches to this type of program both have problems.
One approach is to change the compile commands to enable and disable
features. The other approach is to keep a large file which defines all
the features, and have all other files depend on that. The first can
quickly generate unwieldy command lines. Both require recompiling the
entire program after a change of one option, unless that option only
effects one file, and the automatic building facility used for that
program is defeated. Config provides an alternative that avoids both
of these problems.
1.2 Overview
This config users manual has the following four sections:
Section 1 states what config is used for, describes this manual, and
explains some conventions and terminology used throughout the manual.
It should be read by anyone not already partly familiar with config.
Section 2 explains how, if you have a program already prepared for use
with config and all the appropriate files set up, you would go about
preparing a new configuration of that program. It should be read by
everyone who wishes to rebuild a config-supported program.
Section 3 explains the meaning of the options files in terms of the
program. It should be read by all those who are adding features to a
config-supported program.
Section 4 describes what form a program must be in before it can be
supported by config, and how to set up the initial configuration files
for a program. It should be read by anyone who has a program they
would like config to support.
1.3 Conventions
There are several conventions associated with the use of config that
are assumed to be true throughout this manual. The first is that
config is being used to configure a program, referred to as "the
program." The second is that all the files needed by config are in one
directory, near the top of the source tree for the program. The third
is that that directory is called "conf". It will hereinafter be
referred to as "the conf directory", or just "conf". Config assumes
that at the same level as the conf directory there will be one
directory for every configuration that can currently be built. These
will be called "configuration directories", or "the configuration
directory". The names of these directories are usually in upper case.
In the conf directory, there are two types of files which config cares
about. The first are those with the extension ".options". These are
"options files". The second are conventionally in upper case, and
represent different configurations of the program. For each of these,
there should be a configuration directory with the same name. These
are "configuration files" or "config files". Configuration files and
options files contain lines, each of which is either a comment, or
describes some symbol the programmer uses to control compilation of
the program. These symbols are called options. Currently, config only
supports the configuration of C programs. It could easily support
others, but this document assumes the program is written in C.
2. PREPARING A CONFIGURATION
This section describes the steps necessary to prepare a configuration
file for use in building a configuration of a config-supported
program.
2.1 Syntax
In the conf directory, you should find a collection of options files.
These list all the options that can be used in all configurations of
the program. Some options are required; some can be toggled on or off;
others allow you to change values used by the compiler. The form of
each line in an option file indicates which it is.
The most important rule about options files is that it's line based.
The end of a line is the end of an option. The second thing to know is
that a "#" character followed by a space starts a comment. Everything
after that will be ignored by config, and is for the benefit of the
reader. The meaning of the option is given in the comment. The third
rule is that the first word on the line is the "name" for the option
this line describes, and that everything from the end of the name to
the start of any comment or the end of the line, ignoring any leading
or trailing whitespace, is the "value" for the option this line
describes.
There are two special values for options in the options files. The
first is "required". This means any config file that uses options in
that options file must specify a value for that option (explained
in a later section). The second special value is "option". This
means that the named option is a toggle, and is normally off. It also
changes the format used in the configuration file for that option.
Finally, there is one special name for options: "action". You should
ignore any option lines with that name. All other options allow you to
specify a value for the named option, and list the default value if
you don't specify one.
A required option could look like this, with comments:
system required # which system we're compiling it for
# currently supported: amiga, vms, bsd
A toggle option might look like this, with comments.
no_metakey option # disables the use of "meta" keys as modifiers
# instead of prefacing commands sequences with
# an ESC character
This option, according to the comments, says that "meta" keys are supported
for all configurations unless their config file specifies
"no_metakey".
A non-required value option could look like this:
metabit 0x80 # what bit in a char is the metabit
which says that metabit is normally "0x80", unless the config file
changes it.
2.2 Options Files
Now that you know the syntax for an options file, you can start
reading them. The first one to read is always "config.options". It
describes the options that exist in every configuration of the
program. You should read through config.options, reading the comments
that describe each option (if there are no such comments, you should
find the author of the program or options file and insist that they be
added), and considering what values you would like those options to
have.
First, decide what values the required options should have. These
values will be limited to a small set, and should be listed in the
comments. For example, according to the comments:
system required # which system we're compiling it for
# currently supported: amiga, vms, bsd
the required option "system" can be set to amiga, vms or bsd.
After you've decided what values you want the required options to
have, you should look for options files with the first part of the
names being the values you've chosen. For example, if you wanted
system to be "amiga", you would look for "amiga.options". This file
will list more options that are available for the program if it's
configured with "system" as "amiga". You should read through that file
in the same way you went through config.options. If it has more
required options, you should go through the files associated with
those, and so on. Should you wish to set a required option to a value
for which there is no options file, you should contact the author of
the options file that has that required option in it, or the author of
the program.
2.3 Configuration Files
Having read through all the options files associated with the
configuration you are working on, you can start on your configuration
file. Most people build it as they go. Decide on a name for your file,
and create it in the conf directory - if it isn't already in use.
At the same time, create an empty configuration directory with the
same name. By convention, both these names should be in upper case.
The form of a configuration file is the same as the form of an options
file: name as the first token on the line, value as everything from
the name to any comment or the end of the line, followed by comments,
which start with a "# " and go to the end of the line. For a
configuration file, the name of an option must be an option that
appeared in one of the options file, or the word "option".
The required options must all be listed before any other options. In
addition, the required option whose value names an options file must
be listed before any required options from the options file it names.
So if config.options contained:
system required # which system we're compiling it for
# currently supported: amiga, vms, bsd
and amiga.options contained:
compiler required # which C compiler is being used.
# currently supports only lattice or manx
then your config file might start like:
system amiga
compiler lattice
The remaining options can be listed in any order. Normal value options
are listed the same way that required options are listed. Options
whose value was "option" can be listed in one of two ways. The first
and preferred way is with a line which specifies the name "option",
and then the name of the option you wish to turn on. You can also list
the name of the option as the name on the line, and give it a value of
either "on" or "off", but this form may not be supported in future
versions of config. Config will not complain if you vary from these
forms, but the compiler might when you attempt to compile the program.
The option options default to off, and "name on" is identical to
"option name". So, if you encounter the following two options in
various options files:
no_metakey option # disables the use of "meta" keys as modifiers
# instead of prefacing commands sequences with
# an ESC character
metabit 0x80 # what bit in a char is the metabit
then part of your config file might look like:
option no_metakey # My terminal doesn't support it anyway
metabit 0x100 # For the international character set
which is identical to
no_metakey on
metabit 0x100
Both of these turn on the no_metakey option (thus, according to the
comments, disabling support for the meta key), and change metabit from
its normal value of 0x80 to 0x100.
The final step is to run config on your config file. To do that, make
sure you're in the config directory, and issue the command
config CONFIGFILE
Config will then scan all the appropriate options files and your
config file and prepare your configuration directory for building the
configuration you've specified.
3. PREPARING OPTIONS FILES
This section discusses what config does with the values given to
options, and how that can change the program produced.
3.1 Value Options
Value options are listed in the options or config files with their
name, and the value that will be #defined to their name at compile
time. For section 3.1, assume that the following is in an options file
for the config file and program being configured:
promptwait 20 # number of 10ths of a second to wait before timing
# out while waiting for the user.
For each value option, config creates a file in the configuration
directory whose name is the name of the option, with a ".h" appended.
For the above example, there would be a file "promptwait.h" in the
configuration directory.
That file contains a single define (or in a special case, is empty)
that defines the option name in upper case, and gives it the value
specified (or in a special case, just defines it). So, for the above,
if the config file doesn't change promptwait, the file promptwait.h in
the configuration directory would contain
#define PROMPTWAIT 20
If the config file did change promptwait, for example, reducing it to 10:
promptwait 10
then config would build promptwait.h to indicate that change:
#define PROMPTWAIT 10
3.2 Option Options
Option options are listed in the options files with their name, and
the value "option". They have no value #defined to their names at
compile time - they are either defined or not. For section 3.2, assume
that the following is in an options file for the configuration being
configured:
v11 option # must be defined for the editor to either run on
# or compile on a version 1.1 AmigaDOS system.
# It mainly wards against bugs in the 1.1 ROM Kernel.
Config will create a file whose name is the name of the option, with
".h" appended. So the above option will cause "v11.h" to be created in
the configuration directory. If the option is left off, the file is
left empty. If the option is turned on, the file will define the
option name - once again, in upper case - as a symbol.
So if the v11 option is left off, then the file v11.h will contain
nothing. If some config file turns v11 on, then v11.h will contain
#define V11
As an implementation detail, if any value option has the value
of "on" or "off", it will be treated as if it were an option option,
and either not defined, or just defined with no value attached to the
symbol. This is useful in that it allows for #define symbols whose
existence causes code to appear, and whose value is needed by the code
if it appears.
3.3 Required Options
Required options are listed in the options file with the special value
of "required". They will be given a value in every config file that
uses that options file, and will cause config to check the options
file named by the value given them in the config file.
Like the other kinds of options, required options cause a file whose
name is their name with a ".h" appended to be created in the
configuration directory. Unlike the others, the name of the option is
not what is defined. Instead, the value of the option is defined as a
symbol, once again in upper case. The symbol is not defined to be any
specific value.
For instance, if the options file contained
compiler required # which C compiler is being used.
# currently supports only lattice or manx
Then config will create "compiler.h" in the configuration directory.
If the config file contained this as:
compiler lattice
then the contents of compiler.h would be
#define LATTICE
In addition, the file "lattice.options" will be scanned for further
options when the compiler option is specified in the config file.
If the config file had instead specified "compiler manx", then MANX
would be #defined in compiler.h, and "manx.options" would be scanned.
3.4 Action Options
Action options are specified in options files with a name of "action".
They are never mentioned in config files, and have no direct effect on
the compilation of the program.
What action options do is list commands to be issued to the command
processor after the include files specified by the other options have
been created. The commands are issued in the order they were found in
the options file, and have the configuration directory as their
current working directory when they are issued.
Normally, action commands are used to take care of any preparations
needed before the program can be compiled in the configuration
directory. Examples are copying makefiles into the directory, building
dependency files, or just issuing comments to the user. A typical
short example is:
action lc:lmk -f /amiga/lmkfile depend
action echo "Ready to lmk this configuration of mg."
This issues the command "lc:lmk" with the three arguments "-f",
"/amiga/lmkfile" and "depend" (which, in this cases, creates a new
makefile in the current directory with a dependency list appended to
it), and the command "echo" with the argument '"Ready to lmk this
configuration of mg."' (which, in this case, tells the user that the
configuration directory is ready for the lmk command which will make
the program in it).
3.5 Names To Avoid
There are some names that you can not use when creating options,
mostly became they clash with words that config uses to change the
treatment of that option. Most of these words are external: option,
required, off, on. The following table lists all such words, and
describes where they cannot be used or where they should be used with
care.
word not valid
action as an option name
option as an option name, or the default value for an option
required as the default value for an option
on as an option value
off as an option value
'On' and 'off' are special cases, and can be useful as option values if
used with care. Their use is described above.
In addition, any option name must be valid as the name (without
extension) for a header file on your system. Likewise, any required
option value must be valid as the name for an options file. Finally,
option names and required option values must be valid preprocessor
symbols.
4. PROGRAMMING FOR CONFIG
This section discusses what form a program must be in so that it can
be configured with config.
4.1 Starting Out
Once you've decided that a program will be configured by config, it is
straightforward - but some work - to insure that config can be used to
best advantage. This is best done while the program is still in the
design phase. Converting existing programs for configuration via
config is possible, but painful. See section 4.6 for information on
converting existing programs.
Every time you use a new #defined symbol, you must decide which of
four classes it belongs to:
1) The symbol in some way distinguishes one version from another.
2) The symbol causes features to appear or disappear from some or all
versions.
3) The symbol is a compile-time value that affects some or all
versions.
4) The symbol depends on the values of other symbols in a
predetermined way.
The four cases all require slightly different treatment, and all but
the fourth will be discussed in separate sections. in the fourth
case, the symbol should be dealt with in source code, and no option of
any kind need appear for it in the options files.
4.2 Required Options
Symbols that distinguish versions from one another are almost
certainly "required" options. They usually come in sets of #defined
symbols that are mutually contradictory - if one is on, all the others
must be off. Each such set is represented by one required option,
where the possible values of that required option are the different
symbols that can be defined.
When such a symbol is first referenced, you should determine if it
belongs to such a set that already exists. If so, then change the
comment for the required option for that set to reflect the new
possible value, and then create an empty options file with that value as
the first part of its name, containing a comment describing what it
is.
For example, suppose you add a new symbols "sysv" that is appropriate for
the following option:
system required # which system we're compiling it for
# currently supported: amiga, vms, bsd
Then add ", sysv" to the end of the second comment, and create an
options file "sysv.options", with comment:
#
# support for System V. No options to choose from (yet).
#
Any code that needed to be compiled in - or needed to not be compiled
in - for the System V version of the program would then have it's
conditional compilation depend on the symbol SYSV.
Normally, required options are added to a program after it has been
working in some incarnation for a while - for instance, when it is
being ported to a new machine or operating system. In those cases, if
we are adding a value to a required type, you must find all files that
include the .H file which config creates for that option and check to
see what should be added.
In cases where the required option did not exist before, you need to
choose a name for the option, and add that as a required option in the
appropriate options file with a comment indicating what values it can
take on. You should also create the options files for each of those
values, as above. Finally, every source file that checks for one of
the possible values of the option being defined must be changed to
include the .h file with the name you chose for the required option.
Any automated compilation facilities should be informed of the change
in whatever way is needed.
For example, suppose you are adding support for a second terminal type
to a program - for example, adding termio to a program that already
has termcap support. The option name "tty" or "term" suggests itself,
with the possible values of "termcap" and "termio". So you would add
the following to the appropriate options file:
term required # type of terminal support used. One of:
# termcap, termio
You should also create the files "termcap.options" and
"termio.options", with comments describing what they are. Code should
then appear in the source files conditionally compiled on the symbols
"TERMCAP" and "TERMIO". Any source file that depends on those symbols
should be changed to include the file "term.h".
4.3 Option Options
Any symbols that cause code to be conditionally compiled in, but can
be left on or off without requiring that any other symbols be on or
off (unless they require code that those other symbols control the
compilation of, or something similar) should become "option" options.
When such a symbol is first referenced, all you need to do is add the
name of the symbol and a comment describing it to the appropriate
options file. For example, if you were adding mouse support to a
program, but wanted to allow people to build the program on systems
that didn't have mice attached, you would probably conditionally
compile in that extra code if the symbol "MOUSE" were defined. So you
would add:
mouse option # provide mouse support
Every source file that had code that depended on MOUSE should also
include "mouse.h", as that is where config will put the #define for
MOUSE.
4.4 Value Options
If a defined symbol has a value that is used in the code, then you are
dealing with a "value" option. It is treated the same as an "option"
option, except that the preprocessor symbol will have a value, instead
of merely being defined or not defined.
When such a symbol is first referenced, follow the same actions as the
"option" options, except you must choose a default value for the
option and use that for the value in the options file instead of the
word "option".
For example, if the program had a limit for number of screen lines
built into it, and you wished to make that limit available to the
person compiling the program so they could raise or lower it as
appropriate for their environment. Decide on a reasonable default -
say 70 - and add the following line to the appropriate options file:
maxlines 70 # maximum number of display lines we can work with
You should then change all source files that depend on this maximum to
use the symbol MAXLINES, and have them include "maxlines.h" to get the
value.
You can have a value option do double duty, if you so desire. If one
of the values the option can take on is "off", then the symbol will
not be defined. This allows you to have code that doesn't appear
if the user doesn't want it, and a symbol that holds a needed value in
that code. For example, if word-wrap code were part of a program, and
you wanted it to be either on by default, off by default, or disabled
completely, you might have entries in an option file like so:
wrap 1 # word wrap code. Three values are supported:
# off -> code isn't there at all
# 0 -> code is there, but turned off at startup
# 1 -> code is there, and on at startup.
and C code that looks like:
#ifdef WRAP
int wrap_mode = WRAP ;
#endif
with appropriate code to handle the word wrap.
4.5 The "Appropriate" Options File
The previous three sections each mentioned "the appropriate options
file." This sections discusses how you would find that file.
The matter is actually very simple. The options files for a program
can be viewed as a tree, with "config.options" at the root, and
branches from each options file for the required options in that file.
The various different versions of the program then correspond to the
leaves of this tree. The "appropriate" options file for an option to
be added to would be the options file farthest from the root which
contained all the versions for which that option could apply.
Required options separate versions from one another, and would seem to
require more work. This is seldom the case. Usually, when required
options are first added, there are no options in their options file,
so using the same method as described above will work.
In practice, there usually isn't any problem. When an option is added,
there is a clear idea of what versions it will and won't be
appropriate to add to, and the "appropriate" options file will be
obvious.
4.6 Converting a Program for Config
Converting an existing program for use with config is easy to
describe, and for simple programs, is easy to do. However, if you're
considering converting a program for use with config, it's probably
because the compile-time options have gotten out of hand, so you face
a rather large job.
There are only four steps to convert a program to config: 1) find all
the defined symbols; 2) classify them as described in section 4.1; 3)
create the config.options and all options files needed for required
options; 4) modify the source as appropriate. We will look at each
step in some depth.
Finding all the defined symbols is easy if you have a tool for
selecting lines by pattern from a file. Find all lines that start
with #define or #if in all source files. Delete the preprocessor
directives and any extraneous information, and then sort the results.
At this point, you should have all symbols which are candidates for
options in hand.
Classifying symbols is slightly harder. The previous sections
discusses the various types of symbols and their characteristics.
Start by finding all the symbols which are values for required
options. At this point, you can create a first version of
config.options with the required options and their possible values
listed. You can also create the other options files, with comments
describing what version(s) of the program they provide options for.
The second step should be to identify those symbols which aren't going
to be visible as options to the users. These will have values that can
be determined from the other symbols. You should start adding code (if
it doesn't exist) to define these symbols, based on the values of the
other symbols.
Next, go through the remaining symbols and decide if they are "option"
options or "value" options, and treat them as described in the
preceding sections. By the time you have completed this step, you
should have all the options files finished.
Then go through the source files and add the appropriate #include's
for all defined symbols used in each file, if those symbols are now in
files created by config. Finally, delete the definition of those same
symbols from wherever they were defined previously - either in build
scripts, make files, or .h files.
If you are using automated compilation tools, you should also modify
the data files for those so that the new dependencies are reflected in
them.